#include "App_Mac.h"
#include "utilities.h"
#include <stdio.h>

#include "Commissioning.h"
#include "LoRaMac.h"
#include "board.h"
#include "flash-board.h"
#include "system.h"

DEVICE_STATE_T DeviceState = DEVICE_STATE_INIT;

/*!
 * \brief   Prepares the payload of the frame
 *
 * \retval  [0: frame could be send, 1: error]
 */
bool SendAppData(void* fBuffer, uint16_t appSize)
{
    McpsReq_t mcpsReq;
    LoRaMacTxInfo_t txInfo;

    if (LoRaMacQueryTxPossible(appSize, &txInfo) != LORAMAC_STATUS_OK) {
        // Send empty frame in order to flush MAC commands
        mcpsReq.Type = MCPS_UNCONFIRMED;
        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
        mcpsReq.Req.Unconfirmed.Datarate = SystemParmData.appDataRate;
    } else {
        if (SystemParmData.txConfirmedType == false)  // 确定发送消息的类型为不需要回复的消息
        {
            mcpsReq.Type = MCPS_UNCONFIRMED;
            mcpsReq.Req.Unconfirmed.fPort = SystemParmData.appPort;
            mcpsReq.Req.Unconfirmed.fBuffer = (uint8_t*)fBuffer;
            mcpsReq.Req.Unconfirmed.fBufferSize = appSize;
            mcpsReq.Req.Unconfirmed.Datarate = SystemParmData.appDataRate;
        } else  // 确定发送消息的类型为需要回复ACK的消息
        {
            mcpsReq.Type = MCPS_CONFIRMED;
            mcpsReq.Req.Confirmed.fPort = SystemParmData.appPort;
            mcpsReq.Req.Confirmed.fBuffer = (uint8_t*)fBuffer;
            mcpsReq.Req.Confirmed.fBufferSize = appSize;
            mcpsReq.Req.Confirmed.NbTrials = SystemParmData.appDataNbTrials;
            mcpsReq.Req.Confirmed.Datarate = SystemParmData.appDataRate;
        }
    }

    LoRaMacStatus_t status;
    if ((status = LoRaMacMcpsRequest(&mcpsReq)) == LORAMAC_STATUS_OK) {
        SystemLoRaData.systemState.flagBit.loraTxRunning = 1;  // 标识设备正处于发送数据状态，需要等待回调清除
        SystemLoRaData.systemState.flagBit.loraTxFailed = 0;
        SystemLoRaData.systemState.flagBit.loraTxRunning = 0;
        LOG_PRINTF(LL_DEBUG, "Send Success\r\n");
        return true;
    }
    LOG_PRINTF(LL_DEBUG, "Send Failed, %u\r\n", status);
    return false;
}

bool SendFrame(void)
{
    McpsReq_t mcpsReq;
    LoRaMacTxInfo_t txInfo;

    if (LoRaMacQueryTxPossible(0, &txInfo) != LORAMAC_STATUS_OK) {
        // Send empty frame in order to flush MAC commands
        mcpsReq.Type = MCPS_UNCONFIRMED;
        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
        mcpsReq.Req.Unconfirmed.Datarate = SystemParmData.appDataRate;
    } else {
        if (SystemParmData.txConfirmedType == false)  // 确定发送消息的类型为不需要回复的消息
        {
            mcpsReq.Type = MCPS_UNCONFIRMED;
            mcpsReq.Req.Unconfirmed.fPort = SystemParmData.appPort;
            mcpsReq.Req.Unconfirmed.fBuffer = NULL;   //(uint8_t*)SystemLoRaData.appData;
            mcpsReq.Req.Unconfirmed.fBufferSize = 0;  // SystemLoRaData.appDataSize;
            mcpsReq.Req.Unconfirmed.Datarate = SystemParmData.appDataRate;
        } else  // 确定发送消息的类型为需要回复ACK的消息
        {
            mcpsReq.Type = MCPS_CONFIRMED;
            mcpsReq.Req.Confirmed.fPort = SystemParmData.appPort;
            mcpsReq.Req.Confirmed.fBuffer = NULL;   // (uint8_t*)SystemLoRaData.appData;
            mcpsReq.Req.Confirmed.fBufferSize = 0;  // SystemLoRaData.appDataSize;
            mcpsReq.Req.Confirmed.NbTrials = SystemParmData.appDataNbTrials;
            mcpsReq.Req.Confirmed.Datarate = SystemParmData.appDataRate;
        }
    }

    if (LoRaMacMcpsRequest(&mcpsReq) == LORAMAC_STATUS_OK)  // 发送数据
    {
        SystemLoRaData.systemState.flagBit.loraTxRunning = 1;  // 标识设备正处于发送数据状态，需要等待回调清除
        SystemLoRaData.systemState.flagBit.loraTxFailed = 0;
        SystemLoRaData.systemState.flagBit.loraTxRunning = 0;

        return false;
    }
    return true;
}

/*!
 * \brief Function executed on TxNextPacket Timeout event
 */
static void OnTxNextPacketTimerEvent(void)
{
    MibRequestConfirm_t mibReq;
    LoRaMacStatus_t status;

    TimerStop((void*)(uint8_t*)&(SystemLoRaData.txNextPacketTimer));

    mibReq.Type = MIB_NETWORK_JOINED;
    status = LoRaMacMibGetRequestConfirm(&mibReq);  // 获取LoRaMAC层联网的状态

    if (status == LORAMAC_STATUS_OK) {
        if (mibReq.Param.IsNetworkJoined == true)  // 设备已经入网
        {
            DeviceState = DEVICE_STATE_SEND;
            SystemLoRaData.systemState.flagBit.loraJoin = 0;
            SystemLoRaData.systemState.flagBit.loraJoinFailed = 0;
            SystemLoRaData.systemState.flagBit.loraJoinSuccess = 1;  // 设备入网成功
        } else                                                       // 设备还未入网
        {
            // Network not joined yet. Try to join again
            DeviceState = DEVICE_STATE_JOIN;
        }
    }
}

static char* McpsMcpsToString(Mcps_t mcp)
{
    static char mcps_err[64];
    switch (mcp) {
        case MCPS_UNCONFIRMED: {
            strcpy(mcps_err, "MCPS_UNCONFIRMED");
            break;
        }
        case MCPS_CONFIRMED: {
            strcpy(mcps_err, "MCPS_CONFIRMED");
            break;
        }
        case MCPS_PROPRIETARY: {
            strcpy(mcps_err, "MCPS_PROPRIETARY");
            break;
        }
        case MCPS_MULTICAST: {
            strcpy(mcps_err, "MCPS_MULTICAST");
            break;
        }
        default:
            break;
    }
    return mcps_err;
}

/*!
 * \brief   MCPS-Confirm event function
 *
 * \param   [IN] mcpsConfirm - Pointer to the confirm structure,
 *               containing confirm attributes.
 */
static void McpsConfirm(McpsConfirm_t* mcpsConfirm)
{
    SystemLoRaData.systemState.flagBit.loraTxRunning = 0;  // 标识设备先不处于发送状态
    LOG_PRINTF(LL_DEBUG, "McpsConfirm:Status = %d, McpsRequest: %s\r\n", mcpsConfirm->Status,
               McpsMcpsToString(mcpsConfirm->McpsRequest));
    if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
        SystemLoRaData.systemState.flagBit.loraTxFailed = 0;
        SystemLoRaData.systemState.flagBit.loraTxRunning = 0;
        SystemLoRaData.systemState.flagBit.loraTxSuccess = 1;  // 标识设备发送数据成功
    } else {
        SystemLoRaData.systemState.flagBit.loraTxSuccess = 0;
        SystemLoRaData.systemState.flagBit.loraTxFailed = 1;  // 标识设备发送数据失败
    }
}

/*!
 * \brief   MCPS-Indication event function
 *
 * \param   [IN] mcpsIndication - Pointer to the indication structure,
 *               containing indication attributes.
 */
// 此函数主要是MAC层收到了不是入网回复和信标数据的其他数据回调函数，包含底层发到上层的数据等信息
static void McpsIndication(McpsIndication_t* mcpsIndication)
{
    LOG_PRINTF(LL_DEBUG, "McpsIndication, status = %d\r\n", mcpsIndication->Status);
    if (mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK) {
        return;
    }

    LOG_PRINTF(LL_DEBUG, "receive data: rssi = %d, snr = %d, datarate = %d, fPort = %d, Indication = %s\r\n",
               mcpsIndication->Rssi, (int)mcpsIndication->Snr, (int)mcpsIndication->RxDatarate, mcpsIndication->Port,
               McpsMcpsToString(mcpsIndication->McpsIndication));
    switch (mcpsIndication->McpsIndication) {
        case MCPS_UNCONFIRMED: {
            break;
        }
        case MCPS_CONFIRMED: {
            break;
        }
        case MCPS_PROPRIETARY: {
            break;
        }
        case MCPS_MULTICAST: {
            break;
        }
        default:
            break;
    }

    if (mcpsIndication->RxSlot == 0)  // 接收窗口1，则此信道就是上行数据的信道
    {
    } else  // 接收窗口2
    {
    }
    /*
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->AckReceived = %d\r\n",mcpsIndication->AckReceived);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->DownLinkCounter = %lu\r\n",mcpsIndication->DownLinkCounter);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->FramePending = %d\r\n",mcpsIndication->FramePending);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->Multicast = %d\r\n",mcpsIndication->Multicast);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->Port = %d\r\n",mcpsIndication->Port);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->RxData = %d\r\n",mcpsIndication->RxData);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->RxDatarate = %d\r\n",mcpsIndication->RxDatarate);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->RxSlot = %d\r\n",mcpsIndication->RxSlot);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->Rssi = %d\r\n",mcpsIndication->Rssi);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->Snr = %d\r\n",mcpsIndication->Snr);
        LOG_PRINTF(LL_DEBUG,"mcpsIndication->BufferSize = %d\r\n",mcpsIndication->BufferSize);
        LOG_PRINTF(LL_DEBUG,"\r\n");
    */

    if (SystemLoRaData.systemState.flagBit.loraLinkCheck == 1)  // 如果设备发送了链路检测，则回复链路检测内容
    {
        SystemLoRaData.systemState.flagBit.loraLinkCheck = 0;
    }

    if (mcpsIndication->FramePending == true)  // 服务器指示立即进行数据的发送
    {
        // The server signals that it has pending data to be sent.
        // We schedule an uplink as soon as possible to flush the server.
        OnTxNextPacketTimerEvent();
    }
    // Check Buffer
    // Check BufferSize
    // Check Rssi
    // Check Snr
    // Check RxSlot
    if (mcpsIndication->RxData == true) {
        if (mcpsIndication->BufferSize > 0) {}

        LOG_PRINTF(LL_DEBUG, "Receve data from server:buf = %s,len = %d\r\n", mcpsIndication->Buffer,
                   mcpsIndication->BufferSize);
        for (uint8_t i = 0; i < mcpsIndication->BufferSize; i++) {
            LOG_PRINTF(LL_DEBUG, "0x%0x,", mcpsIndication->Buffer[i]);
        }
        LOG_PRINTF(LL_DEBUG, "\r\n");

        App_At_Command_Parase(mcpsIndication->Buffer, mcpsIndication->BufferSize);
    }
}

/*!
 * \brief   MLME-Confirm event function
 *
 * \param   [IN] mlmeConfirm - Pointer to the confirm structure,
 *               containing confirm attributes.
 */
// 此函数的主要功能是对与进行的MAC指令请求或者入网请求数据的回调函数
static void MlmeConfirm(MlmeConfirm_t* mlmeConfirm)
{
    static uint8_t preferChannelTimes = 0;
    LOG_PRINTF(LL_DEBUG, "MlmeConfirm: Status = %d, DemodMargin = %d, NbGateways = %d, NbRetries = %d\r\n",
               mlmeConfirm->Status, mlmeConfirm->DemodMargin, mlmeConfirm->NbGateways, mlmeConfirm->NbRetries);

    SystemLoRaData.systemState.flagBit.loraTxRunning = 0;
    SystemLoRaData.systemState.flagBit.loraTxSuccess = 1;
    SystemLoRaData.systemState.flagBit.loraTxFailed = 0;
    switch (mlmeConfirm->MlmeRequest) {
        case MLME_JOIN: {
            if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
                LOG_PRINTF(LL_DEBUG, "join network OK!\r\n");
                // Status is OK, node has joined the network
                SystemLoRaData.systemState.flagBit.loraJoin = 0;
                SystemLoRaData.systemState.flagBit.loraJoinFailed = 0;
                SystemLoRaData.systemState.flagBit.loraJoinSuccess = 1;
                DeviceState = DEVICE_STATE_TIME_CHECK;
            } else {
                MibRequestConfirm_t mibReq;
                if ((SystemParmData.perferChannel == 1) && (preferChannelTimes == 0)) {
                    preferChannelTimes++;

                    uint16_t channelsMaskTemp[6] = {0};

                    if ((SystemParmData.perferChannelIndex >= 0) && (SystemParmData.perferChannelIndex < 16)) {
                        channelsMaskTemp[0] = 0x0001 << (SystemParmData.perferChannelIndex);
                    } else if ((SystemParmData.perferChannelIndex >= 16) && (SystemParmData.perferChannelIndex < 32)) {
                        channelsMaskTemp[1] = 0x0001 << (SystemParmData.perferChannelIndex - 16 * 1);
                    } else if ((SystemParmData.perferChannelIndex >= 32) && (SystemParmData.perferChannelIndex < 48)) {
                        channelsMaskTemp[2] = 0x0001 << (SystemParmData.perferChannelIndex - 16 * 2);
                    } else if ((SystemParmData.perferChannelIndex >= 48) && (SystemParmData.perferChannelIndex < 64)) {
                        channelsMaskTemp[3] = 0x0001 << (SystemParmData.perferChannelIndex - 16 * 3);
                    } else if ((SystemParmData.perferChannelIndex >= 64) && (SystemParmData.perferChannelIndex < 80)) {
                        channelsMaskTemp[4] = 0x0001 << (SystemParmData.perferChannelIndex - 16 * 4);
                    } else if ((SystemParmData.perferChannelIndex >= 80) && (SystemParmData.perferChannelIndex < 96)) {
                        channelsMaskTemp[5] = 0x0001 << (SystemParmData.perferChannelIndex - 16 * 5);
                    }

                    mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
                    mibReq.Param.ChannelsDefaultMask = channelsMaskTemp;
                    LoRaMacMibSetRequestConfirm(&mibReq);
                    mibReq.Type = MIB_CHANNELS_MASK;
                    mibReq.Param.ChannelsMask = channelsMaskTemp;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    SystemParmData.appDataRate = SystemParmData.perferDataRate;

                    mibReq.Type = MIB_CHANNELS_DATARATE;
                    mibReq.Param.ChannelsDatarate = SystemParmData.perferDataRate;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE;
                    mibReq.Param.ChannelsDatarate = SystemParmData.perferDataRate;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    mibReq.Type = MIB_ADR;
                    mibReq.Param.AdrEnable = 0;
                    LoRaMacMibSetRequestConfirm(&mibReq);  // 关闭数据速率自适应

                    DeviceState = DEVICE_STATE_JOIN;
                } else if ((SystemParmData.perferChannel == 1) && (preferChannelTimes > 0)) {
                    preferChannelTimes = 0;
                    SystemParmDataLoad();

                    mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
                    mibReq.Param.ChannelsDefaultMask = (void*)SystemParmData.channelsMask;
                    LoRaMacMibSetRequestConfirm(&mibReq);
                    mibReq.Type = MIB_CHANNELS_MASK;
                    mibReq.Param.ChannelsMask = (void*)SystemParmData.channelsMask;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    mibReq.Type = MIB_CHANNELS_DATARATE;
                    mibReq.Param.ChannelsDatarate = SystemParmData.appDataRate;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE;
                    mibReq.Param.ChannelsDatarate = SystemParmData.appDataRate;
                    LoRaMacMibSetRequestConfirm(&mibReq);

                    mibReq.Type = MIB_ADR;
                    mibReq.Param.AdrEnable = SystemParmData.adrType;
                    LoRaMacMibSetRequestConfirm(&mibReq);  // 关闭数据速率自适应

                    LOG_PRINTF(LL_DEBUG, "join failed\r\n");
                    SystemLoRaData.systemState.flagBit.loraJoin = 0;
                    SystemLoRaData.systemState.flagBit.loraJoinFailed = 1;
                    SystemLoRaData.systemState.flagBit.loraJoinSuccess = 0;
                } else {
                    DeviceState = DEVICE_STATE_JOIN;
                    LOG_PRINTF(LL_DEBUG, "join failed\r\n");
                    SystemLoRaData.systemState.flagBit.loraJoin = 0;
                    SystemLoRaData.systemState.flagBit.loraJoinFailed = 1;
                    SystemLoRaData.systemState.flagBit.loraJoinSuccess = 0;
                }
            }
            break;
        }
        case MLME_LINK_CHECK: {
            if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) {
                // Check DemodMargin
                // Check NbGateways
            } else {
            }
            break;
        }
        case MLME_DEVICE_TIME:
            LOG_PRINTF(LL_DEBUG, "Mlme Device Time OK\r\n");
            SystemLoRaData.systemState.flagBit.loraDeviceTiming = 0;
            SystemLoRaData.systemState.flagBit.loraDeviceTime = 1;  // 如果设备发送了时间对时，则回复时间对时内容

            break;
        default:
            break;
    }
}

/*!
 * \brief   MLME-Indication event function
 *
 * \param   [IN] mlmeIndication - Pointer to the indication structure.
 */
static void MlmeIndication(MlmeIndication_t* mlmeIndication)
{
    switch (mlmeIndication->MlmeIndication) {
        case MLME_SCHEDULE_UPLINK: {  // The MAC signals that we shall provide an uplink as soon as possible
            OnTxNextPacketTimerEvent();
            break;
        }
        default:
            break;
    }
}

static void lwan_dev_params_update(void)
{
    MibRequestConfirm_t mibReq;

    mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
    mibReq.Param.ChannelsDefaultMask = (uint16_t*)SystemParmData.channelsMask;
    LoRaMacMibSetRequestConfirm(&mibReq);
    mibReq.Type = MIB_CHANNELS_MASK;
    mibReq.Param.ChannelsMask = (uint16_t*)SystemParmData.channelsMask;
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Param.Rx2Channel.Frequency = SystemParmData.rx2Channel.Frequency;
    LOG_PRINTF(LL_DEBUG, "frequency = %lu\r\n", mibReq.Param.Rx2Channel.Frequency);
    mibReq.Param.Rx2Channel.Datarate = SystemParmData.rx2Channel.Datarate;

    mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;  // 设置入网的信道参数
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Type = MIB_RX2_CHANNEL;  // 设置入网的信道参数
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Type = MIB_DEVICE_CLASS;  // 设置入网类型
    mibReq.Param.Class = SystemParmData.deviceClass;
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Type = MIB_ADR;
    mibReq.Param.AdrEnable = SystemParmData.adrType;
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Type = MIB_CHANNELS_TX_POWER;
    mibReq.Param.ChannelsTxPower = SystemParmData.power;
    LoRaMacMibSetRequestConfirm(&mibReq);
}

void AppMacInit(LoRaMacPrimitives_t* LoRaMacPrimitives, LoRaMacCallback_t* LoRaMacCallbacks)
{
    MibRequestConfirm_t mibReq;
    LoRaMacPrimitives->MacMcpsConfirm = McpsConfirm;
    LoRaMacPrimitives->MacMcpsIndication = McpsIndication;
    LoRaMacPrimitives->MacMlmeConfirm = MlmeConfirm;
    LoRaMacPrimitives->MacMlmeIndication = MlmeIndication;
    LoRaMacCallbacks->GetBatteryLevel = NULL;
    LoRaMacInitialization(LoRaMacPrimitives, LoRaMacCallbacks,
                          ACTIVE_REGION);  // 初始化应用层的函数指针和底层之间的关联，并初始化LoRa的相关参数
    TimerInit((void*)&(SystemLoRaData.txNextPacketTimer), OnTxNextPacketTimerEvent);

    mibReq.Type = MIB_ADR;
    mibReq.Param.AdrEnable = SystemParmData.adrType;
    LoRaMacMibSetRequestConfirm(&mibReq);

    mibReq.Type = MIB_PUBLIC_NETWORK;
    mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
    LoRaMacMibSetRequestConfirm(&mibReq);

    lwan_dev_params_update();

    return;
}

bool AppMacJoin(void)
{
    MlmeReq_t mlmeReq;
    MibRequestConfirm_t mibReq;
    if (SystemParmData.activitionType != 0) {
        mlmeReq.Type = MLME_JOIN;
        mlmeReq.Req.Join.DevEui = (uint8_t*)SystemParmData.devEui;
        mlmeReq.Req.Join.AppEui = (uint8_t*)SystemParmData.appEui;
        mlmeReq.Req.Join.AppKey = (uint8_t*)SystemParmData.appKey;
        mlmeReq.Req.Join.NbTrials = SystemParmData.appDataNbTrials;

        SystemLoRaData.systemState.flagBit.loraJoin = 1;
        SystemLoRaData.systemState.flagBit.loraJoinFailed = 0;
        SystemLoRaData.systemState.flagBit.loraJoinSuccess = 0;
        return (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK);
    }
    return false;
}

bool AppMacLinkCheck(void)
{
    MlmeReq_t mlmeReq;
    MibRequestConfirm_t mibReq;

    mibReq.Type = MIB_NETWORK_JOINED;
    LoRaMacMibGetRequestConfirm(&mibReq);  // 获取LoRaMAC层联网的状态

    if (mibReq.Param.IsNetworkJoined == true) {
        SystemLoRaData.systemState.flagBit.loraLinkCheck = 1;  // 标识设备正在进行网络连接检测
        mlmeReq.Type = MLME_LINK_CHECK;
        LoRaMacMlmeRequest(&mlmeReq);

        LOG_PRINTF(LL_DEBUG, "LinkCheck request\r\n");

        LoRaMacMlmeRequest(&mlmeReq);  // 发送MAC请求
    } else {
        DeviceState = DEVICE_STATE_JOIN;
        return false;
    }
    return true;
}

bool AppMacDeviceTimeCheck(void)
{
    MlmeReq_t mlmeReq;
    MibRequestConfirm_t mibReq;

    mibReq.Type = MIB_NETWORK_JOINED;
    LoRaMacMibGetRequestConfirm(&mibReq);  // 获取LoRaMAC层联网的状态

    LOG_PRINTF(LL_DEBUG, "Device Mlme time, NetworkJoined = %d\r\n", mibReq.Param.IsNetworkJoined);
    if (mibReq.Param.IsNetworkJoined == true) {
        SystemLoRaData.systemState.flagBit.loraDeviceTiming = 1;  // 标识设备正在进行时间对时检测
        mlmeReq.Type = MLME_DEVICE_TIME;
        LoRaMacStatus_t status = LoRaMacMlmeRequest(&mlmeReq);
        LOG_PRINTF(LL_DEBUG, "Device Mlme time, Request Status = %u\r\n", status);
        if (status != LORAMAC_STATUS_OK) {
            SystemLoRaData.systemState.flagBit.loraDeviceTiming = 0;
            return false;
        }
        return true;
    } else {
        DeviceState = DEVICE_STATE_JOIN;
        return false;
    }
    return true;
}

void AppMacSendData()
{
    MibRequestConfirm_t mibReq;

    mibReq.Type = MIB_NETWORK_JOINED;
    LoRaMacMibGetRequestConfirm(&mibReq);  // 获取LoRaMAC层联网的状态

    if (mibReq.Param.IsNetworkJoined == true) {
        SendFrame();  // 发送数据帧
    } else {
        DeviceState = DEVICE_STATE_JOIN;
    }
    LOG_PRINTF(LL_DEBUG, "--------SendFrame:xSemaphoreGive\r\n");
    // SystemLoRaData.systemState.flagBit.loraMutexState = 0;
    // if ((SystemLoRaData.loraTxMutex != NULL) && (SystemLoRaData.systemState.flagBit.loraMutexState)) {}
}

bool AppMacStateCheck()
{
    MibRequestConfirm_t mibReq;

    mibReq.Type = MIB_NETWORK_JOINED;
    LoRaMacMibGetRequestConfirm(&mibReq);  // 获取LoRaMAC层联网的状态
    return (mibReq.Param.IsNetworkJoined == true);
}
